package org.render;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;

import org.geom.Point2D;
import org.geom.Point3D;
import org.geom.curve.ICurve;

public class CurveRenderer3D extends Engine3D {

	//protected ICurve contextCurve;
	//protected Point3D currentPoint = new Point3D();
	//protected float currentT = 0;
	private Dimension viewPort;
	
	//---------------------------------------------------------------------- constructor
	public CurveRenderer3D(ICurve curve, Dimension viewPort) {
		this.viewPort = viewPort;
	}
	

	//---------------------------------------------------------------------- render
	//@Override
	public void render(ICurve curve, Graphics g) {
		updateMatrix();
		
		drawAxis(g);
		drawCurve(curve.getPoints(), g);
		drawLocalCoordinates(curve.getCurrentPoint(), curve, g);
		drawCurvePoints(curve.getPoints(), g);
	}
	
	@Override
	protected void updateMatrix(){
		
        u1 = viewPort.width - 1;
        v0 = viewPort.height - 1;

        super.updateMatrix();
	}
	
	//---------------------------------------------------------------------- privates
	
	protected void drawLocalCoordinates(Point3D currentPoint, ICurve curve, Graphics g) {
		// TODO text coordinates
		drawCurrentPoint(currentPoint, g);
		drawTangentVector(currentPoint, curve, g);
		drawBinormalVector(currentPoint, curve, g);
		drawNormalVector(currentPoint, curve, g);
	}

	protected void drawCurrentPoint(Point3D point, Graphics g) {
		int k = 10;
		Point2D p = this.transformCoordinateOnRotationMatrix(point);
		g.setColor(new Color(0,132,209));
		g.fillOval((int)p.x-k/2, (int)p.y-k/2, k, k);
	}

	protected void drawTangentVector(Point3D point, ICurve curve, Graphics g) {
		Point3D p1 = new Point3D();
		Point3D p2 = new Point3D();
		Point3D tangentVector = curve.tangent(curve.getCurrentT());
		
		/* 
		 * disegno un segmento formato da 2 punti appartenenti alla retta 
		 * passante per P(t) punto sulla curva E(t) ---> point
		 * e parallela al vettore tangente alla curva in P ---> derivata di Elicoide su currentT
		
		 * la retta passante per P0 e parallela al vettore <a,b,c> 
		 * parametrizzata sulla variabile m
		 * è determinata da queste equazioni:
		 * x = x0 + a * m
		 * y = y0 + b * m
		 * z = z0 + c * m
		 * (nota: è una retta e ha un solo parametro.)
		 
		 */
		
		/*p1.x = point.x + tangentVector.x * 0;
		p1.y = point.y + tangentVector.y * 0;
		p1.z = point.z + tangentVector.z * 0;*/
		p1 = point;
		
		p2.x = point.x + tangentVector.x * 40f;
		p2.y = point.y + tangentVector.y * 40f;
		p2.z = point.z + tangentVector.z * 40f;

		g.setColor(Color.RED);
		this.drawString3D("t", p2, g);
		drawLine3D(p1, p2, g);
	}

	protected void drawBinormalVector(Point3D point, ICurve curve, Graphics g) {
		Point3D p1 = new Point3D();
		Point3D p2 = new Point3D();
		
		/*
		 * Idem con patate come sopra: 
		 * retta passante per un punto e perpendicolare al vettore binormale.
		 */ 
		 
		Point3D binormalVector = curve.binormal(curve.getCurrentT());//.normalize();
		
		/*p1.x = point.x + binormalVector * 0;
		p1.y = point.y + binormalVector * 0;
		p1.z = point.z + binormalVector * 0;*/
		p1 = point;
		
		p2.x = point.x + binormalVector.x * 40f;
		p2.y = point.y + binormalVector.y * 40f;
		p2.z = point.z + binormalVector.z * 40f;
		
		g.setColor(Color.BLUE);
		this.drawString3D("b", p2, g);
		drawLine3D(p1, p2, g);
	}
	
	private void drawNormalVector(Point3D point,  ICurve curve, Graphics g) {
		Point3D p1 = new Point3D();
		Point3D p2 = new Point3D();
		Point3D normalVector = curve.normal(curve.getCurrentT());//.normalize();
		
		/*p1.x = point.x + binormalVector * 0;
		p1.y = point.y + binormalVector * 0;
		p1.z = point.z + binormalVector * 0;*/
		p1 = point;
		
		p2.x = point.x + normalVector.x * 40f;
		p2.y = point.y + normalVector.y * 40f;
		p2.z = point.z + normalVector.z * 40f;
		
		g.setColor(Color.GREEN);
		this.drawString3D("n", p2, g);
		drawLine3D(p1, p2, g);
	}


	protected void drawCurvePoints(ArrayList<Point3D> points, Graphics g) {
		Point2D pt;
		
		for(Point3D p : points) {
			pt = transformCoordinateOnRotationMatrix(p);
			g.setColor(new Color(10,10,10,20));
			g.fillOval((int)pt.x-3, (int)pt.y-3, 6, 6);
			g.drawOval((int)pt.x-3, (int)pt.y-3, 6, 6);
		}
	}

	protected void drawCurve(ArrayList<Point3D> points, Graphics g) {
		Point3D pre = points.get(0);//new Point3D();
		
		for(Point3D p : points) {
			g.setColor(Color.BLACK);
			drawLine3D(pre, p, g);
			pre = p;
		}
	}

	protected void drawAxis(Graphics g) {
		Point3D o = new Point3D();
		Point3D x = new Point3D(30,0,0);
		Point3D y = new Point3D(0,30,0);
		Point3D z = new Point3D(0,0,30);
		
		g.setColor(new Color(192, 192, 192));
		drawLine3D(o,x,g);
		drawLine3D(o,y,g);
		drawLine3D(o,z,g);
		
		drawString3D("x", x, g);
		drawString3D("y", y, g);
		drawString3D("z", z, g);
	}


}
